/*
 *  Copyright 2011 yura.
 * 
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 * 
 *       http://www.apache.org/licenses/LICENSE-2.0
 * 
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *  under the License.
 */
package org.opu.vcforms.vcapi;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import org.hibernate.HibernateException;
import org.hibernate.SessionFactory;
import org.hibernate.classic.Session;
import org.hibernate.jdbc.Work;
import org.opu.vcforms.datasource.DataReceiver;

/**
 *
 * @author yura
 */
public class SessionDataReceiver implements DataReceiver {

    private SessionFactory sessionFactory;

    /** Life cicle of current object is one statement */
    private ResultSet tmpResultSet;
    /** Life cicle of current object is one statement */
    private ResultSetMetaData tpmMetaData;
    /** Life cicle of current object is one statement */
    private Session session;

    public SessionDataReceiver(SessionFactory sessionFactory) {
        this.sessionFactory = sessionFactory;
    }

    @Override
    public boolean sendQuery(final String query) {
        if (session != null) {
            try {
                session.close();
            } catch (HibernateException ex) {
                ex.printStackTrace(System.err);
            }
        }

        try {
            session = sessionFactory.openSession();
            session.doWork(new Work() {

                @Override
                public void execute(Connection connection) throws SQLException {
                    Statement statement = connection.createStatement(
                            ResultSet.TYPE_SCROLL_INSENSITIVE,
                            ResultSet.CONCUR_UPDATABLE);

                    tmpResultSet = statement.executeQuery(query);
                    tpmMetaData = tmpResultSet.getMetaData();
                }
            });

            return true;
        } catch (HibernateException ex) {
            System.err.println(getClass().getName() + ":");
            System.err.println("\tError - " + ex);
            System.err.println("\tQUERY - " + query);
            return false;
        }

    }

    @Override
    public int getColumns() {
        if (isQuerySent()) {
            try {
                return tpmMetaData.getColumnCount();
            } catch (SQLException ex) {
                return 0;
            }
        } else {
            return 0;
        }
    }

    @Override
    public int getRows() {
        if (isQuerySent()) {
            try {
                tmpResultSet.last();
                return tmpResultSet.getRow();
            } catch (Exception ex) {
                return 0;
            }
        } else {
            return 0;
        }
    }

    @Override
    public String[] getHeads() {
        if (isQuerySent()) {
            try {
                ResultSetMetaData metaData = tmpResultSet.getMetaData();
                int count = metaData.getColumnCount();

                List<String> l = new ArrayList<String>(count);

                for (int i = 1; i <= count; i++) {
                    l.add(metaData.getColumnName(i));
                }

                return l.toArray(new String[count]);
            } catch (Exception ex) {
                return new String[]{""};
            }
        } else {
            return new String[]{""};
        }
    }

    @Override
    public Object getObject(int row, String col) {
        if (isQuerySent()) {
            try {
                if (tmpResultSet.absolute(row)) {
                    return tmpResultSet.getObject(col);
                }

                return "";
            } catch (Exception ex) {
                return "";
            }
        } else {
            return "";
        }
    }

    @Override
    public Object getObject(int row, int col) {
        if (isQuerySent()) {
            try {
                if (tmpResultSet.absolute(row)) {
                    return tmpResultSet.getObject(col);
                }

                return "";
            } catch (Exception ex) {
                return "";
            }
        } else {
            return "";
        }
    }

    private boolean isQuerySent() {
        return tmpResultSet != null;
    }

    @Override
    protected SessionDataReceiver clone() throws CloneNotSupportedException {
        return new SessionDataReceiver(sessionFactory);
    }
}
